#pragma once
#include <iostream>
#include "../Int/Int.h"
#include "../../Functions/Math/min.h"

#ifdef FLOAT_ARRAY_ALLOC_MAX
#if FLOAT_ARRAY_ALLOC_MAX < 1
#error An array must be able to accommodate at least 1 item (Source: FLOAT_ARRAY_ALLOC_MAX < 1).
#endif
#endif


class DoubleArray
{
private:
	double *data;
public:
	Int size;

	DoubleArray(double number);
	template <typename arg, typename ...args>
	DoubleArray(arg number, args ...arguments);

	double& operator[] (int index);

	void append(double number);
	template <typename arg, typename ...args>
	void append(arg number, args ...arguments);

	void insert(double number, int index);
	void free();
};

DoubleArray::DoubleArray(double number)
{
	this->size = 1;
	this->data = new double[this->size];
	this->data[0] = number;
}

template <typename arg, typename ...args>
DoubleArray::DoubleArray(arg number, args ...arguments)
{
	this->size = 1;
	this->data = new double[this->size];
	this->data[0] = number;
#ifdef FLOAT_ARRAY_ALLOC_MAX
	if (FLOAT_ARRAY_ALLOC_MAX > this->size)
	{
		append(arguments...);
	}
#else
	append(arguments...);
#endif // FLOAT_ARRAY_ALLOC_MAX
}

void DoubleArray::append(double number)
{
	double *temp = new double[this->size];
	for (int i = 0; i < this->size; i++)
	{
		temp[i] = this->data[i];
	}

#ifdef FLOAT_ARRAY_ALLOC_MAX
	if (FLOAT_ARRAY_ALLOC_MAX > this->size)
	{
		this->size++;
		this->data = new double[this->size];
		for (int i = 0; i < (this->size - 1); i++)
		{
			this->data[i] = temp[i];
		}
		this->data[this->size - 1] = number;
	}
#else
	this->size++;
	this->data = new double[this->size];
	for (int i = 0; i < (this->size - 1); i++)
	{
		this->data[i] = temp[i];
	}
	this->data[this->size - 1] = number;
#endif // FLOAT_ARRAY_ALLOC_MAX

	temp = new double;
	delete temp;
	temp = NULL;
}

template <typename arg, typename ...args>
void DoubleArray::append(arg number, args ...arguments)
{
	double *temp = new double[this->size];
	for (int i = 0; i < this->size; i++)
	{
		temp[i] = this->data[i];
	}

#ifdef FLOAT_ARRAY_ALLOC_MAX
	if (FLOAT_ARRAY_ALLOC_MAX > this->size)
	{
		this->size++;
		this->data = new double[this->size];
		for (int i = 0; i < (this->size - 1); i++)
		{
			this->data[i] = temp[i];
		}
		this->data[this->size - 1] = number;
	}
#else
	this->size++;
	this->data = new double[this->size];
	for (int i = 0; i < (this->size - 1); i++)
	{
		this->data[i] = temp[i];
	}
	this->data[this->size - 1] = number;
#endif // FLOAT_ARRAY_ALLOC_MAX

	temp = new double;
	delete temp;
	temp = NULL;

#ifdef FLOAT_ARRAY_ALLOC_MAX
	if (FLOAT_ARRAY_ALLOC_MAX > this->size)
	{
		append(arguments...);
	}
#else
	append(arguments...);
#endif // FLOAT_ARRAY_ALLOC_MAX
}

void DoubleArray::insert(double number, int index)
{
	double *temp = new double[this->size];
	for (int i = 0; i < this->size; i++)
	{
		temp[i] = this->data[i];
	}

	this->size++;
	this->data = new double[this->size];
#ifdef ARRAY_FIRST
	for (int i = 0; i < (index - ARRAY_FIRST); i++)
	{
		this->data[i] = temp[i];
	}

	this->data[index - ARRAY_FIRST] = number;
#ifdef FLOAT_ARRAY_ALLOC_MAX
	for (int i = (index - ARRAY_FIRST + 1); i < min(FLOAT_ARRAY_ALLOC_MAX, this->size); i++)
	{
		this->data[i] = temp[i - 1];
	}
#else // FLOAT_ARRAY_ALLOC_MAX
	for (int i = (index - ARRAY_FIRST + 1); i < this->size; i++)
	{
		this->data[i] = temp[i - 1];
	}
#endif // FLOAT_ARRAY_ALLOC_MAX

#else // ARRAY_FIRST
	for (int i = 0; i < (index); i++)
	{
		this->data[i] = temp[i];
	}

	this->data[index] = number;
#ifdef FLOAT_ARRAY_ALLOC_MAX
	for (int i = (index + 1); i < min(FLOAT_ARRAY_ALLOC_MAX, this->size); i++)
	{
		this->data[i] = temp[i - 1];
	}
#else // FLOAT_ARRAY_ALLOC_MAX
	for (int i = (index + 1); i < this->size; i++)
	{
		this->data[i] = temp[i - 1];
	}
#endif // FLOAT_ARRAY_ALLOC_MAX
#endif // ARRAY_FIRST

	temp = new double;
	delete temp;
	temp = NULL;
}

void DoubleArray::free()
{
	this->data = new double;
	delete this->data;
	this->data = NULL;
	this->size.free();
}

double& DoubleArray::operator[] (int index)
{
#ifdef ARRAY_FIRST
	return this->data[index - ARRAY_FIRST];
#else
	return this->data[index];
#endif // ARRAY_FIRST
}